package com.zktr.utils;

import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;

import com.zktr.bean.BrandBean;
import com.zktr.bean.CategoryBean;
import com.zktr.pojo.Brand;
import com.zktr.pojo.Category;



/**
 * Apache的版本一 当需要对对象属性 拷贝的时候，需要用到Spring 反射机制
 *        版本二 cglib版本，动态代理
 * 原理，都使用静态类调用，最终转化虚拟机中两个单例的工具对象。
 * @author yf
 *
 */
public class BeanCopyUtils {

   /*
    *对象属性 拷贝 
    *反射
    * */
	public void copyBean(BrandBean initial, Brand end) {
		//ConvertUtils.register(new DateConvert(), java.util.Date.class);全局自定义注册
		ConvertUtils.register(new Converter(){
			//@Override注解，当你要重写父类的方法时，需要加入此注解，用来检查方法的正确性
			//方法重写，子类方法与父类某一方法的方法名、参数列表、返回值相同时覆盖父类的方法
			@Override
			public Object convert(@SuppressWarnings("rawtypes") Class type, Object value) {
				if(value==null){
					return null;
				}
				String str=(String) value;
				if(str.trim().isEmpty()){
					return null;
				}
				SimpleDateFormat s=new SimpleDateFormat();
				try {
					return s.parse(str);
				} catch (ParseException e) {
					throw new RuntimeException();
				}
			}
			
		}, Date.class);
		
		try {
			//PropertyUtilsBean的copyProperties方法实现了拷贝的算法，属性复制根据需要进行转换
			/*
			 *   动态bean：orig instanceof DynaBean：Object value = ((DynaBean)orig).get(name);然后把value复制到动态bean类

			 *   Map类型：orig instanceof Map：key值逐个拷贝

			 *   其他普通类：：从beanInfo【每一个对象都有一个缓存的bean信息，包含属性字段等】取出name，然后把sourceClass和targetClass逐个拷贝
			 * 
			 * */
			BeanUtils.copyProperties(initial, end);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}

	}  
	
	
	/**
	 * 将请求对象转化为Bean对象
	 * @param request 请求对象
	 * @param 要设置Bean的类型,传入试为: Bean.class
	 * @return
	 */
	public static <T> T requestToBean(HttpServletRequest request, Class<T> c) {
		try {
			T t = c.newInstance();
			   //获取页面所有的请求参数名称
			Enumeration<String> e = request.getParameterNames();
			while (e.hasMoreElements()) {
				//获取参数名称
				String name = e.nextElement();
				String value = request.getParameter(name);
				BeanUtils.setProperty(t, name, value);
			}
			return t;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}

	}
	/**

	* 将dto和entity之间的属性互相转换,dto中属性一般为String等基本类型,

	* 但是entity中可能有复合主键等复杂类型,需要注意同名问题

	* @param src

	* @param target

	*/

	public static Object populate(Object src, Object target) {

	Method[] srcMethods = src.getClass().getMethods();

	Method[] targetMethods = target.getClass().getMethods();

	for (Method m : srcMethods) {

	String srcName = m.getName();

	if (srcName.startsWith("get")) {

	try {

	Object result = m.invoke(src);

	for (Method mm : targetMethods) {

	String targetName = mm.getName();

	if (targetName.startsWith("set") && targetName.substring(3, targetName.length())

	.equals(srcName.substring(3, srcName.length()))) {

	mm.invoke(target, result);

	}

	}

	} catch (Exception e) {

	 

	}

	}

	}

	return target;

	}

	/**

	* dto集合和实体类集合间的互相属性映射

	* @param src

	* @param target

	* @param targetClass

	* @return

	*/

	@SuppressWarnings("unchecked")

	public static <S,T> List<T> populateList(List<S> src,List<T> target,Class<?> targetClass){

	for(int i = 0;i<src.size();i++){

	try {

	Object object = targetClass.newInstance();

	target.add((T) object);

	populate(src.get(i),object);

	 

	} catch (Exception e) {

	continue;//某个方法反射异常

	} 

	}

	return target;

	}
	
}

